package com.king.base.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import javax.mail.internet.MimeMessage;
import java.io.File;
import java.util.Map;

/**
 * @description 发送邮件工具，支持发送纯文本邮件、html邮件、附件邮件、thymeleaf模板邮件类型。
 * @author Spur
 * @date 2019/9/17
 */
@Component
public class MailClient {
    private final Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * Java邮件发送器
     */
    @Autowired
    private JavaMailSenderImpl mailSender;
    /**
     * thymeleaf模板引擎
     */
    @Autowired
    private TemplateEngine templateEngine;
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * 发送不含附件，且不含嵌入html静态资源页面的纯文本简单邮件
     *
     * @param deliver
     *            发送人邮箱名 如： javalsj@163.com
     * @param receivers
     *            收件人，可多个收件人 如：11111@qq.com,2222@163.com
     * @param carbonCopys
     *            抄送人，可多个抄送人 如：33333@sohu.com
     * @param subject
     *            邮件主题 如：您收到一封高大上的邮件，请查收。
     * @param text
     *            邮件内容 如：测试邮件逗你玩的。
     */
    public void sendSimpleEmail(String deliver, String[] receivers, String[] carbonCopys, String subject, String text)
            throws Exception {

        sendMimeMail(deliver, receivers, carbonCopys, subject, text, false, null);
    }

    /**
     * 发送含嵌入html静态资源页面， 但不含附件的邮件
     *
     * @param deliver
     *            发送人邮箱名 如： javalsj@163.com
     * @param receivers
     *            收件人，可多个收件人 如：11111@qq.com,2222@163.com
     * @param carbonCopys
     *            抄送人，可多个抄送人 如：3333@sohu.com
     * @param subject
     *            邮件主题 如：您收到一封高大上的邮件，请查收。
     * @param text
     *            邮件内容 如： <html><body>
     *            <h1>213123</h1></body></html>
     */
    public void sendHtmlEmail(String deliver, String[] receivers, String[] carbonCopys, String subject, String text)
            throws Exception {
        sendMimeMail(deliver, receivers, carbonCopys, subject, text, true, null);
    }

    /**
     * 发送含附件，但不含嵌入html静态资源页面的邮件
     *
     * @param deliver
     *            发送人邮箱名 如： javalsj@163.com
     * @param receivers
     *            收件人，可多个收件人 如：11111@qq.com,2222@163.com
     * @param carbonCopys
     *            抄送人，可多个抄送人 如：3333@sohu.com.cn
     * @param subject
     *            邮件主题 如：您收到一封高大上的邮件，请查收。
     * @param text
     *            邮件内容 如：测试邮件逗你玩的。
     * @param attachmentFilePaths
     *            附件文件路径 如：http://www.javalsj.com/resource/test.jpg,
     *            http://www.javalsj.com/resource/test2.jpg
     */
    public void sendAttachmentsEmail(String deliver, String[] receivers, String[] carbonCopys, String subject,
                                     String text, String[] attachmentFilePaths) throws Exception {
        mailSender.setUsername(username);
        mailSender.setPassword(password);
        sendMimeMail(deliver, receivers, carbonCopys, subject, text, false, attachmentFilePaths);
    }

    /**
     * 发送含附件，且含嵌入html静态资源页面的邮件
     *
     * @param deliver
     *            发送人邮箱名 如： javalsj@163.com
     * @param receivers
     *            收件人，可多个收件人 如：11111@qq.com,2222@163.com
     * @param carbonCopys
     *            抄送人，可多个抄送人 如：33333@jiuqi.com.cn
     * @param subject
     *            邮件主题 如：您收到一封高大上的邮件，请查收。
     * @param text
     *            <html><body><img src=\"cid:test\"><img
     *            src=\"cid:test2\"></body></html>
     * @param attachmentFilePaths
     *            附件文件路径 如：http://www.javalsj.com/resource/test.jpg,
     *            http://www.javalsj.com/resource/test2.jpg
     *            需要注意的是addInline函数中资源名称attchmentFileName需要与正文中cid:attchmentFileName对应起来
     */
    public void sendHtmlAndAttachmentsEmail(String deliver, String[] receivers, String[] carbonCopys, String subject,
                                            String text, String[] attachmentFilePaths) throws Exception {
        sendMimeMail(deliver, receivers, carbonCopys, subject, text, true, attachmentFilePaths);
    }

    /**
     * 发送thymeleaf模板邮件
     *
     * @param deliver
     *            发送人邮箱名 如： javalsj@163.com
     * @param receivers
     *            收件人，可多个收件人 如：11111@qq.com,2222@163.com
     * @param carbonCopys
     *            抄送人，可多个抄送人 如：33333@sohu.com
     * @param subject
     *            邮件主题 如：您收到一封高大上的邮件，请查收。
     * @param thymeleafTemplatePath
     *            邮件模板 如：mail\mailTemplate.html。
     * @param thymeleafTemplateVariable
     *            邮件模板变量集
     */
    public void sendTemplateEmail(String deliver, String[] receivers, String[] carbonCopys, String subject, String thymeleafTemplatePath,
                                  Map<String, Object> thymeleafTemplateVariable) throws Exception {
        String text = null;
        if (thymeleafTemplateVariable != null && thymeleafTemplateVariable.size() > 0) {
            Context context = new Context();
            thymeleafTemplateVariable.forEach((key, value)->context.setVariable(key, value));
            text = templateEngine.process(thymeleafTemplatePath, context);
        }
        sendMimeMail(deliver, receivers, carbonCopys, subject, text, true, null);
    }

    /**
     * 发送的邮件(支持带附件/html类型的邮件)
     *
     * @param deliver
     *            发送人邮箱名 如： javalsj@163.com
     * @param receivers
     *            收件人，可多个收件人 如：11111@qq.com,2222@163.com
     * @param carbonCopys
     *            抄送人，可多个抄送人 如：3333@sohu.com
     * @param subject
     *            邮件主题 如：您收到一封高大上的邮件，请查收。
     * @param text
     *            邮件内容 如：测试邮件逗你玩的。 <html><body><img
     *            src=\"cid:attchmentFileName\"></body></html>
     * @param attachmentFilePaths
     *            附件文件路径 如：
     *            需要注意的是addInline函数中资源名称attchmentFileName需要与正文中cid:attchmentFileName对应起来
     * @throws Exception
     *             邮件发送过程中的异常信息
     */
    private void sendMimeMail(String deliver, String[] receivers, String[] carbonCopys, String subject, String text,
                              boolean isHtml, String[] attachmentFilePaths) throws Exception {
        StopWatch stopWatch = new StopWatch();
        try {
            stopWatch.start();
            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
            helper.setFrom(deliver);
            helper.setTo(receivers);
            if(carbonCopys !=null && carbonCopys.length>0){
                helper.setCc(carbonCopys);
            }
            helper.setSubject(subject);
            helper.setText(text, isHtml);
            // 添加邮件附件
            if (attachmentFilePaths != null && attachmentFilePaths.length > 0) {
                for (String attachmentFilePath : attachmentFilePaths) {
                    File file = new File(attachmentFilePath);
                    if (file.exists()) {
                        FileSystemResource fileSystemResource = new FileSystemResource(file);
                        helper.addAttachment(fileSystemResource.getFilename(), fileSystemResource);
                    }
                }
            }
            mailSender.send(mimeMessage);
            stopWatch.stop();
            logger.info("邮件发送成功, 花费时间{}秒", stopWatch.getTotalTimeSeconds());
        } catch (Exception e) {
            logger.error("邮件发送失败, 失败原因 :{} 。", e.getMessage(), e);
            throw e;
        }
    }

}

